﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using BrightIdeasSoftware;
using MovieBrowser.Controller;
using MovieBrowser.Event;
using MovieBrowser.Model;
using MovieBrowser.Presentation.Events;
using MovieBrowser.Presentation.Forms.Db;
using MovieBrowser.Presentation.Forms.Dialogs;
using MovieBrowser.Presentation.List.SearchDialogs;
using MovieBrowser.Util;

namespace MovieBrowser.Presentation.List
{
    public partial class PersonListView : UserControl, IPersonList, IDebugLogEvent
    {
        public MovieBrowserController Controller { get; set; }

        #region Events
        public event EventHandler MovieSelectionChange;
        public event EventHandler CopyMovies;
        public event EventHandler Enqueue;
        public event EventHandler DebugText;
        public event EventHandler MovieSearch;
        //
        public void InvokeOnMovieSearchCriteriaClick(CriteriaSearchEventArgs e)
        {
            EventHandler handler = MovieSearch;
            if (handler != null) handler(this, e);
        }
        //
        public void InvokeOnDebugText(Exception exception)
        {
            var handler = DebugText;
            if (handler != null) handler(this, new DebugTextEventArgs(exception));
        }
        public void InvokeOnDebugText(string text)
        {
            var handler = DebugText;
            if (handler != null) handler(this, new DebugTextEventArgs(text));
        }
        //
        public void InvokeOnMovieSelectionChange(EventArgs e)
        {
            var handler = MovieSelectionChange;
            if (handler != null) handler(this, e);
        }
        //
        public void InvokeCopyMovies(CopyMoviesEventArgs e)
        {
            var handler = CopyMovies;
            if (handler != null) handler(this, e);
        }
        //
        public void InvokeEnqueue(CopyMoviesEventArgs e)
        {
            EventHandler handler = Enqueue;
            if (handler != null) handler(this, e);
        }
        #endregion

        public PersonListView()
        {
            InitializeComponent();
            datalistResult.Font = Properties.Settings.Default.ListFont;
        }

        private void TbUserPrefWishClick(object sender, EventArgs e)
        {
            tbUserPrefWish.Checked = !tbUserPrefWish.Checked;
            SearchByUserPref();
        }

        private void TbUserPrefLikeClick(object sender, EventArgs e)
        {
            tbUserPrefLike.Checked = !tbUserPrefLike.Checked;

            try
            {
                var person = ((Person)datalistResult.SelectedObject);
                var fav = Controller.Db.UserFavoritePersons.Where(o => o.Person.Id == person.Id && o.User.Id == Authorization.LoggedInUser.Id && o.Attribute == "Favorite").FirstOrDefault();
                var user = Controller.Db.Users.Where(o => o.Id == Authorization.LoggedInUser.Id).FirstOrDefault();
                if (fav == null)
                {

                    fav = new UserFavoritePerson()
                    {
                        Person = person,
                        User = user,
                        Attribute = "Favorite",
                        Value = tbUserPrefLike.Checked.ToString()
                    };
                    person.Favorite = Boolean.Parse(fav.Value);
                    Controller.Db.AddToUserFavoritePersons(fav);
                    Controller.Db.SaveChanges();
                }
                else
                {
                    fav.Value = tbUserPrefLike.Checked.ToString();
                    person.Favorite = Boolean.Parse(fav.Value);
                    Controller.Db.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }

        private void TbUserPrefDislikeClick(object sender, EventArgs e)
        {
            tbUserPrefDislike.Checked = !tbUserPrefDislike.Checked;
            if (tbUserPrefDislike.Checked) tbUserPrefLike.Checked = false;
            SearchByUserPref();
        }

        private void TbUserPrefWatchedClick(object sender, EventArgs e)
        {
            tbUserPrefWatched.Checked = !tbUserPrefWatched.Checked;
            SearchByUserPref();
        }

        private void TbUserPrefHaveClick(object sender, EventArgs e)
        {

            tbUserPrefHave.Checked = !tbUserPrefHave.Checked;
            SearchByUserPref();
        }

        private void SearchTextSearchStarted(object sender, EventArgs e)
        {
            ComponentUtility.TimedFilter(datalistResult, searchText.Text);

        }
        private void SearchTextSearchCancelled(object sender, EventArgs e)
        {
            ComponentUtility.TimedFilter(datalistResult, searchText.Text);

        }

        private void DatalistResultDoubleClick(object sender, EventArgs e)
        {
            if (datalistResult.SelectedObject != null)
                Controller.SearchPerson(MovieBrowserController.ImdbName, (Person)datalistResult.SelectedObject);

        }

        private void DatalistResultKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                SearchMoviesByPerson();
            else if (e.KeyCode == Keys.Delete)
                DeletePeople();
        }

        private void SearchMoviesByPerson()
        {
            if (datalistResult.SelectedObject != null)
            {
                var movies = new List<Movie>();

                movies.AddRange(Controller.Db.Actors.Where(o => o.Person.Id == ((Person)datalistResult.SelectedObject).Id).Select(o => o.Movie));
                movies.AddRange(Controller.Db.Directors.Where(o => o.Person.Id == ((Person)datalistResult.SelectedObject).Id).Select(o => o.Movie));
                movies.AddRange(Controller.Db.Writers.Where(o => o.Person.Id == ((Person)datalistResult.SelectedObject).Id).Select(o => o.Movie));
                InvokeOnMovieSearchCriteriaClick(new CriteriaSearchEventArgs(typeof(Person), movies));
                //                Controller.SearchPerson(MovieBrowserController.ImdbSearch, (Person)datalistResult.SelectedObject);
            }
        }


        private void SearchByUserPref()
        {
            if (Authorization.IsAuthorized)
            {
                var people = Controller.Db.People.ToList();

                //if (tbUserPrefLike.Checked)
                //{
                //    var list = Controller.Db.MoviePersonalNotes.Where(o => o.User.Id == Authorization.LoggedInUser.Id && o.Favourite > 0).Select(o => o.Movie);
                //    movies = movies.Intersect(list);
                //}
                //if (tbUserPrefDislike.Checked)
                //{
                //    var list = Controller.Db.MoviePersonalNotes.Where(o => o.User.Id == Authorization.LoggedInUser.Id && o.Favourite < 0).Select(o => o.Movie);
                //    movies = movies.Intersect(list);
                //}
                if (tbUserPrefWish.Checked)
                {
                    var list = Controller.Db.UserFavoritePersons.Where(o => o.User.Id == Authorization.LoggedInUser.Id && o.Attribute == "Favorite" && o.Value == "True").Select(o => o.Person);
                    people = people.Intersect(list).ToList();
                }
                //if (tbUserPrefWatched.Checked)
                //{
                //    var list = Controller.Db.MoviePersonalNotes.Where(o => o.User.Id == Authorization.LoggedInUser.Id && o.Seen).Select(o => o.Movie);
                //    movies = movies.Intersect(list);
                //}
                //if (tbUserPrefHave.Checked)
                //{
                //    var list = Controller.Db.MoviePersonalNotes.Where(o => o.User.Id == Authorization.LoggedInUser.Id && o.Have).Select(o => o.Movie);
                //    movies = movies.Intersect(list);
                //}

                datalistResult.DataSource = people;
            }
        }


        public Person SelectedPerson { get { return datalistResult.SelectedObject as Person; } }

        public IList<Person> SelectedPersons { get { return datalistResult.SelectedObjects.Cast<Person>().ToList(); } }

        public void UpdateNode(Movie movie)
        {
            //            Controller.UpdatePersonNode(SelectedMovie, movie);
        }

        public void LoadResults(IEnumerable<Movie> movies)
        {
            datalistResult.DataSource = movies;
        }

        private void TbUpdateNodesClick(object sender, EventArgs e)
        {
            Controller.UpdatePersonInformation(SelectedPersons, Controller);
        }


        //Form Getters


        // ReSharper disable MemberCanBeMadeStatic.Local
        private void DatalistResultFormatRow(object sender, BrightIdeasSoftware.FormatRowEventArgs e)
        // ReSharper restore MemberCanBeMadeStatic.Local
        {
            var person = (Person)e.Model;
            if (person.Favorite)
            {
                e.Item.BackColor = Color.PaleTurquoise;
            }
        }

        private void SendToPendriveToolStripMenuItemClick(object sender, EventArgs e)
        {
            OnCopyMovies();
        }

        private void OnCopyMovies(bool enqueue = false)
        {
            var movies = new List<Movie>();
            foreach (Movie movie in datalistResult.SelectedObjects)
            {
                var movie1 = movie;
                var filesystems = Controller.Db.MovieFilesystems.Where(o => o.Movie.Id == movie1.Id).ToList();
                switch (filesystems.Count)
                {
                    case 1:
                        movie.FilePath = filesystems[0].FolderPath;
                        movies.Add(movie);
                        break;
                    case 0:
                        continue;
                    default:
                        {
                            var selectMovie = new SelectMovie(movie, filesystems);

                            selectMovie.ShowDialog(this);
                            if (String.IsNullOrEmpty(selectMovie.SelectedLocation)) continue;
                            movie.FilePath = selectMovie.SelectedLocation;
                            movies.Add(movie);
                        }
                        break;
                }
            }


            if (movies.Count > 0)
            {

                if (!enqueue)
                {
                    InvokeCopyMovies(new CopyMoviesEventArgs(movies));
                }
                else
                {
                    InvokeEnqueue(new CopyMoviesEventArgs(movies));
                }
            }
        }

        private void AddToQueueToolStripMenuItemClick(object sender, EventArgs e)
        {
            OnCopyMovies(true);
        }

        private void ToolStripButton1Click(object sender, EventArgs e)
        {
            Controller.Refresh();
            LoadPersonList();
        }

        private void LoadPersonList()
        {
            if (Authorization.IsAuthorized)
            {
                var persons = Controller.Db.People.Select(o => o);
                var list = Controller.Db.UserFavoritePersons.Where(o => o.User.Id == Authorization.LoggedInUser.Id && o.Attribute == "Favorite" && o.Value == "True").Select(o => o.Person);

                foreach (var fav in list)
                {
                    var p = persons.Where(o => o.Id == fav.Id).FirstOrDefault();
                    p.Favorite = true;
                }
                datalistResult.DataSource = persons.ToList();
            }
            else
            {
                var persons = Controller.Db.People.Select(o => o);
                datalistResult.DataSource = persons.ToList();
            }
        }

        public void UpdatePerson(Person person)
        {
        }

        public event EventHandler PersonSelectionChanged;

        private void tsDeletePerson_Click(object sender, EventArgs e)
        {
            DeletePeople();
        }

        public void DeletePeople()
        {
            if (MessageBox.Show("Sure to delete selected people?", "Confirm", MessageBoxButtons.YesNoCancel) ==
                DialogResult.Yes)
            {
                foreach (OLVListItem p in datalistResult.SelectedItems)
                {
                    try
                    {
                        Controller.Db.DeleteObject(p.RowObject);
                        Controller.Db.SaveChanges();
                        datalistResult.RemoveObject(p.RowObject);
                        datalistResult.Items.Remove(p);
                    }
                    catch
                    {
                    }
                }
            }
        }

        private void tsEditForm_Click(object sender, EventArgs e)
        {
            try
            {
                Person p = (Person)datalistResult.SelectedObject;
                PersonGridForm gridForm = new PersonGridForm(Controller, p.Id);
                gridForm.Show(this);
            }
            catch
            {

            }
        }

        private void tsUpdateCount_Click(object sender, EventArgs e)
        {
            List<Person> list = SelectedPersons.ToList();
            var thread = new Thread(() =>
                                        {
                                            foreach (var person in list)
                                            {
                                                InvokeOnDebugText("Updating Work Count for " + person.Name);
                                                Controller.UpdatePersonWorks(person);
                                            }
                                        });
            thread.Start();
        }

        private void datalistResult_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (Authorization.IsAuthorized)
            {
                var person = (Person)datalistResult.SelectedObject;

                if (person != null)
                {
                    var fav = Controller.Db.UserFavoritePersons.Where(o => o.User.Id == Authorization.LoggedInUser.Id && o.Person.Id == person.Id && o.Attribute == "Favorite").FirstOrDefault();
                    if (fav != null)
                    {
                        tbUserPrefLike.Checked = Boolean.Parse(fav.Value);
                    }
                    else
                    {
                        tbUserPrefLike.Checked = false;
                    }
                }
                else
                {
                    tbUserPrefLike.Checked = false;
                }
            }
            else
            {
                tbUserPrefLike.Checked = false;
            }
        }

        public void ShowGroup(bool group)
        {
            datalistResult.ShowGroups = group;
        }

        public void UpdateFont(System.Drawing.Font font)
        {
            datalistResult.Font = font;
        }

        private void tbMoviesByPerson_Click(object sender, EventArgs e)
        {
            SearchMoviesByPerson();
        }

        private void datalistResult_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Middle)
            {
                SearchMoviesByPerson();
            }
        }
    }
}
